<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .only-message {
        color: brown;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <!-- 没有内容，因此没有文本节点 -->
      <div id="emptyStr"></div>
      <!-- 有空格，因此有一个文本节点 -->
      <div id="onlySpace"></div>
      <!-- 有内容，因此有一个文本节点 -->
      <div id="fullStr">Hello World!</div>
    </div>
  </body>
  <script>
    /* 1.Text 节点由 Text 类型表示，包含按字面解释的纯文本，也可能包含转义后的 HTML 字符，但不含 HTML 代码。
     * 2.Text 类型的节点具有以下特征
     *   + nodeType 等于 3；
     *   + nodeName 值为"#text"；
     *   + nodeValue 值为节点中包含的文本；
     *   + parentNode 值为 Element 对象；
     *   + 不支持子节点；
     * 3.Text 节点中包含的文本可以通过 nodeValue 属性访问，也可以通过 data 属性访问，这两个属性包含相同的值。
     * 4.修改 nodeValue 或 data 的值，也会在另一个属性反映出来。
     * 5.暴露的方法
     *   + appendData(text)，向节点末尾添加文本 text；
     *   + deleteData(offset, count)，从位置 offset 开始删除 count 个字符；
     *   + insertData(offset, text)，在位置 offset 插入 text；
     *   + replaceData(offset, count, text)，用 text 替换从位置 offset 到 offset + count 的文本；
     *   + splitText(offset)，在位置 offset 将当前文本节点拆分为两个文本节点；
     *   + substringData(offset, count)，提取从位置 offset 到 offset + count 的文本。
     * 6.还可以通过 length 属性获取文本节点中包含的字符数量。这个值等于 nodeValue.length 和 data.length。
     * 7.默认情况下，包含文本内容的每个元素最多只能有一个文本节点。
     * 8.只要节点在当前的文档树中，这样的修改就会马上反映出来。
     * 9.修改文本节点还有一点要注意，就是HTML 或 XML 代码（取决于文档类型）会被转换成实体编码，即小于号、大于号或引号会被转义
     *
     */
    function checkedText() {
      //1.测试元素之前文本节点的数目
      let emptyStr = document.getElementById("emptyStr");
      let onlySpace = document.getElementById("onlySpace");
      let fullStr = document.getElementById("fullStr");
      console.log(
        emptyStr.childNodes,
        onlySpace.childNodes,
        fullStr.childNodes
      );
      //NodeList [] NodeList [text] NodeList [text]
      //2.获取文本节点
      let textNode = onlySpace.firstChild; //设置emptyStr报错，因为其本身不存在文本节点，故而无法设置文本节点值。
      //3.设置节点文本内容
      textNode.nodeValue = "Some other message";
      //4.查看文本内容转义
      //输出为"Some &lt;strong&gt;other&lt;/strong&gt; message"
      textNode.nodeValue = "Some<strong>other</strong>message";
      fullStr.firstChild.nodeValue =
        "Some &lt;strong&gt;other&lt;/strong&gt; message";
    }
    // checkedText();

    /** 2.创建文本节点
     *    a.document.createTextNode()可以用来创建新文本节点，它接收一个参数，即要插入节点的文本。
     *    b.跟设置已有文本节点的值一样，这些要插入的文本也会应用 HTML 或 XML 编码。
     *    c.一般来说一个元素只包含一个文本子节点，不过，也可以让元素包含多个文本子节点。
     *    d.在将一个文本节点作为另一个文本节点的同胞插入后，两个文本节点的文本之间不会包含空格。
     * **/
    function checkCreateTextNode() {
      //1.创建单个文本节点并被添加到页面上
      let dom1 = document.createElement("DIV");
      dom1.style.fontSize = "25px";
      dom1.className = "only-message";
      let textNode = document.createTextNode("Hello world!!!");
      dom1.appendChild(textNode);
      document.body.appendChild(dom1);
      //2.创建多个文本节点
      let dom2 = document.createElement("div");
      dom2.style.fontSize = "20px";
      let textNode1 = document.createTextNode("HELLO");
      let textNode2 = document.createTextNode("WORDDDDD");
      dom2.appendChild(textNode1);
      dom2.appendChild(textNode2);
      document.body.appendChild(dom2);
    }
    //  checkCreateTextNode();

    /** 3.规范化文本节点
     *    a.DOM 文档中的同胞文本节点可能导致困惑，因为一个文本节点足以表示一个文本字符串。
     *    b.同样，DOM 文档中也经常会出现两个相邻文本节点。
     *    c.为此，有一个方法可以合并相邻的文本节点。这个方法叫 normalize()，是在 Node 类型中定义的（因此所有类型的节点上都有这个方法）。在包含两个或多个相邻
     *      文本节点的父节点上调用 normalize()时，所有同胞文本节点会被合并为一个文本节点，这个文本节点的 nodeValue 就等于之前所有同胞节点 nodeValue 拼接
     *      在一起得到的字符串。
     *    d.浏览器在解析文档时，永远不会创建同胞文本节点。同胞文本节点只会出现在 DOM 脚本生成的文档树中。
     * **/
    function checkNormalize() {
      let element = document.createElement("div");
      element.className = "message";
      let textNode = document.createTextNode("Hello world!");
      element.appendChild(textNode);
      let anotherTextNode = document.createTextNode("Yippee!");
      element.appendChild(anotherTextNode);
      document.body.appendChild(element);
      console.log(element.childNodes);//NodeList(2) [text, text]
      console.log(element.firstChild.nodeValue);//Hello world!
      element.normalize();
      console.log(element.childNodes);//NodeList [text]
      console.log(element.firstChild.nodeValue);//Hello world!Yippee!
    }
    // checkNormalize();

    /** 4.拆分文本节点
     *    a.Text 类型定义了一个与 normalize()相反的方法——splitText()。这个方法可以在指定的偏移位置拆分 nodeValue，将一个文本节点拆分成两个文本节点。
     *    b.拆分之后，原来的文本节点包含开头到偏移位置前的文本，新文本节点包含剩下的文本。
     *    c.这个方法返回新的文本节点，具有与原来的文本节点相同的 parentNode。
     *    d.拆分文本节点最常用于从文本节点中提取数据的 DOM 解析技术。
     * **/
     function checkSplitText(){
       let dom = document.createElement('DIV');
       dom.style.fontSize = '30px';
       let textNode = document.createTextNode('HELLO');
       let anotherTextNode = document.createTextNode('WORD!!');
       dom.appendChild(textNode);
       dom.appendChild(anotherTextNode);
       dom.normalize();
       console.log(dom.childNodes);//NodeList [text]
       document.body.appendChild(dom);
       let newTextNode = dom.firstChild.splitText('3');
       console.log(dom.firstChild.nodeValue);//HEL
       console.log(newTextNode.nodeValue);//LOWORD!!
       console.log(dom.childNodes);//NodeList(2) [text, text]
     }
     checkSplitText();
  </script>
</html>
